﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using ImplementationJeu;
using InterfaceJeu;


namespace InterfaceHommeMachine
{
    /// <summary>
    /// Logique d'interaction pour MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        Dictionary<String, Object> info;
        InterfaceJeu.Jeu monJeu ;
        InterfaceJeu.Joueur joueurcourant;
        Unite uniteCourante;
        InterfaceJeu.Ville villeCourante;
        Dictionary<InterfaceJeu.Coordonnees,int> tableRectangle; 
        Dictionary<InterfaceJeu.Coordonnees, int> tableRectangleDeco;
        List<InterfaceJeu.Coordonnees> listecaseChargee;

        // Texture flyweigth
        Texture tex;
        TestCase test;

        /// <summary>
        /// Constructeur de fenetre principale
        /// initialise les variables
        /// </summary>
        /// <param name="lesinfos">les informations issue de la fentre de lancement</param>
        /// <param name="nouvellepartie"> indique s'il s'agit d'une nouvelle partie ou non</param>
        public MainWindow(Dictionary<string, object> lesinfos, bool nouvellepartie)
        {
            tableRectangle = new Dictionary<InterfaceJeu.Coordonnees, int>();
            tableRectangleDeco = new Dictionary<InterfaceJeu.Coordonnees, int>();
            info = lesinfos;
            tex = new Texture();
            test = new TestCase();
            listecaseChargee = new List<InterfaceJeu.Coordonnees>();
            Console.Write("est \n");
            InitializeComponent();
            // creation du jeu
            if(nouvellepartie)
                creationDuJeu();
            monJeu = ImplementationJeu.Jeu.Instance;
            //Console.Write(joueurcourant);
           // Console.Write(monJeu.Joueurs);
           // Console.Write(monJeu.sonTour);
           // Console.Write(monJeu.Joueurs[monJeu.sonTour]);
            joueurcourant = monJeu.Joueurs[monJeu.sonTour];
            uniteCourante = null;
            villeCourante = null;
            Title = "Chargement de la carte en cours... Veuillez patientez...";
                        
        }

        /// <summary>
        /// Creer un nouveau jeu
        /// </summary>
        private void creationDuJeu()
        {
            InterfaceJeu.Joueur j1 = new ImplementationJeu.Joueur((string)info["Joueur1"], System.Drawing.Color.Red, (string)info["Civ1"]);
            InterfaceJeu.Joueur j2 = new ImplementationJeu.Joueur((string)info["Joueur2"], System.Drawing.Color.Blue, (string)info["Civ2"]);
            List<InterfaceJeu.Joueur> lj = new List<InterfaceJeu.Joueur>();
            lj.Add(j1);
            lj.Add(j2);
            if ((int)info["nbjoueur"] == 3)
            {
                InterfaceJeu.Joueur j3 = new ImplementationJeu.Joueur((string)info["Joueur3"], System.Drawing.Color.Green, (string)info["Civ3"]);
                lj.Add(j3);
            }
            if ((int)info["nbjoueur"] == 4)
            {
                InterfaceJeu.Joueur j3 = new ImplementationJeu.Joueur((string)info["Joueur3"], System.Drawing.Color.Green, (string)info["Civ3"]);
                InterfaceJeu.Joueur j4 = new ImplementationJeu.Joueur((string)info["Joueur4"], System.Drawing.Color.Orange, (string)info["Civ4"]);
                lj.Add(j3);
                lj.Add(j4);
            }
            monJeu = ImplementationJeu.Jeu.Instance;
            monJeu.demarrerNouveuJeu(lj, (int)info["Taille"]);

        }
        
        /// <summary>
        /// Methode appellée quand la fenêtre principale est chargée
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            buildContext();
            initCarte(joueurcourant);
            Title = "Civil INSA tion : Les départements en guerre !";
            
        }

        /// <summary>
        /// Construit le contexte nécessaire pour créer les autres élément de l'interface
        /// </summary>
        private void buildContext()
        {
            int taille =  monJeu.Carte.TailleCote *50;
            gridMap.Width = taille;
            gridMap.Height = taille;
            gridUnite.Width = taille;
            gridUnite.Height = taille;
            gridVille.Width = taille;
            gridVille.Height = taille;
            canvas1.Width = taille;
            canvas1.Height = taille;
            for (int i = 0; i < monJeu.Carte.TailleCote; i++)
            {
                gridMap.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(50, GridUnitType.Pixel) });
                gridMap.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(50, GridUnitType.Pixel) });
                gridVille.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(50, GridUnitType.Pixel) });
                gridVille.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(50, GridUnitType.Pixel) });
                gridUnite.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(50, GridUnitType.Pixel) });
                gridUnite.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(50, GridUnitType.Pixel) });
            }
            initInfoCivi();
            initScroll();
            initLabelTour();
        }

        /// <summary>
        /// Initialise la carte en fonction d'un joueur
        /// Affiche les rectangles correspondant aux cases visible par ce joueur
        /// et creer ces rectangles s'ils n'existent pas
        /// </summary>
        /// <param name="joueur">le joueur a partir duquel on doit initialiser la carte</param>
       private void initCarte(InterfaceJeu.Joueur joueur){
           cacherCarte();
           List<InterfaceJeu.Coordonnees> listecaseVisible = joueur.updateCasesVisibles();
           foreach (InterfaceJeu.Coordonnees coord in listecaseVisible)
           {
               if (listecaseChargee.Contains(coord))
               {
                   var rectangle = (Rectangle)gridMap.Children[tableRectangle[coord]];
                   rectangle.Visibility = Visibility.Visible;
                   if (tableRectangleDeco.ContainsKey(coord))
                   {
                       var rec = (Rectangle)gridMap.Children[tableRectangleDeco[coord]];
                       rec.Visibility = Visibility.Visible;
                   }
               }
               else
               {
                   InterfaceJeu.Case casecarte = monJeu.Carte.obtenirCase(coord);
                   var rectangle = createRectangle(coord.abscisse, coord.ordonnee, casecarte);
                   gridMap.Children.Add(rectangle);
                   tableRectangle.Add(coord, gridMap.Children.Count - 1);
                   listecaseChargee.Add(coord);
                  
               }
           }
           initVille(listecaseVisible);
           initUnite(listecaseVisible);
       }

        /// <summary>
        /// Cache tout les elements de la carte
        /// </summary>
       private void cacherCarte()
       {
           foreach (UIElement elem in gridMap.Children)
           {
               elem.Visibility = Visibility.Hidden;
           }
       }

        /// <summary>
        /// Creer un rectangle avec une texture différente suivant le type de la case à placée
        /// cette méthode est récursive dans le cas ou la case à placée est un décorateur
        /// </summary>
        /// <param name="c">la colonne ou on doit afficher le rectangle</param>
       /// <param name="l">la ligne ou on doit afficher le rectangle</param>
        /// <param name="caseAPlacer">la case correspond au retangle dans le moteur</param>
        /// <returns>le rectangle à ajouté au enfant de la grille représentant la carte</returns>
        private Rectangle createRectangle(int c, int l, InterfaceJeu.Case caseAPlacer)
        {
            Rectangle rectangle = new Rectangle();
            rectangle.Width = 50;
            rectangle.Height = 50;
            InterfaceJeu.Coordonnees coord = new ImplementationJeu.Coordonnees(c, l);
            if (caseAPlacer is DecorateurCaseSpeciale)
            {
                DecorateurCaseSpeciale deco = (DecorateurCaseSpeciale)caseAPlacer;
                Rectangle rec = createRectangle(c, l, deco.caseAppliq);
                gridMap.Children.Add(rec);
                tableRectangleDeco.Add(coord, gridMap.Children.Count - 1);
                if (caseAPlacer is Fer)
                    rectangle.Fill = tex.getImage("Fer");
                else if (caseAPlacer is Fruit)
                    rectangle.Fill = tex.getImage("Fruit");
            }
            else if (caseAPlacer is CaseDesert)
                rectangle.Fill = tex.getImage("Desert");
            else if (caseAPlacer is CaseMontagne)
                rectangle.Fill = tex.getImage("Montagne");
            else if (caseAPlacer is CasePlaine)
                rectangle.Fill = tex.getImage("Plaine");                       
            Grid.SetColumn(rectangle, c);
            Grid.SetRow(rectangle, l);
            rectangle.MouseLeftButtonDown += new MouseButtonEventHandler(rectangle_MouseLeftDown);
            rectangle.MouseRightButtonDown += new MouseButtonEventHandler(rectangle_MouseRightDown);
            return rectangle;
        }

        /// <summary>
        ///  Initialise les rectangles représentant les unités
        /// en fonction de la liste des cases visible par un joueur
        /// Nb les directeurs on une texture spéciale
        /// </summary>
        /// <param name="lc">la liste des cases visibles par un joueur</param>
        private void initUnite(List<InterfaceJeu.Coordonnees> lc)
        {
            gridUnite.Children.RemoveRange(0, gridUnite.Children.Count);
            foreach (InterfaceJeu.Joueur j in monJeu.Joueurs)
            {
                Brush b = Texture.convertirCouleur(j.couleur);
                 foreach (InterfaceJeu.Coordonnees c in test.contientUnite(j))
                 {
                     if (lc.Contains(c))
                     {
                          var rectangle = new Rectangle();
                         rectangle.Width = 50;
                         rectangle.Height = 50;
                         rectangle.Stroke = b;
                         Grid.SetColumn(rectangle, c.abscisse);
                         Grid.SetRow(rectangle, c.ordonnee);                       
                         rectangle.MouseLeftButtonDown += new MouseButtonEventHandler(unite_MouseLeftDown);
                         rectangle.MouseRightButtonDown += new MouseButtonEventHandler(rectangle_MouseRightDown);
                         InterfaceJeu.Directeur dir =monJeu.Joueurs[monJeu.sonTour].civilisation.chef;
                         InterfaceJeu.Civilisation civ = monJeu.Joueurs[monJeu.sonTour].civilisation;
                         if (dir!=null && c.Equals(dir.position))
                         {
                             if (civ is CivilisationEII)
                                 rectangle.Fill = tex.getImage("Eii");
                             if (civ is CivilisationGCU)
                                 rectangle.Fill = tex.getImage("Gc");
                             if (civ is CivilisationGMA)
                                 rectangle.Fill = tex.getImage("Gma");
                             if (civ is CivilisationINFO)
                                 rectangle.Fill = tex.getImage("Info");
                             if (civ is CivilisationSGM)
                                 rectangle.Fill = tex.getImage("Mnt");
                             if (civ is CivilisationSRC)
                                 rectangle.Fill = tex.getImage("Src");
                             if (civ is CivilisationSTPI)
                                 rectangle.Fill = tex.getImage("Stpi");
                         }
                         gridUnite.Children.Add(rectangle);    
                     }
                 }
            }
        }

        /// <summary>
        /// Initialise les rectangles représentant les villes
        /// en fonction de la liste des cases visible par un joueur
        /// </summary>
        /// <param name="lc">la liste des cases visibles par un joueur</param>
        private void initVille(List<InterfaceJeu.Coordonnees> lc)
        {
            gridVille.Children.RemoveRange(1, gridVille.Children.Count);
            foreach (InterfaceJeu.Joueur joueur in monJeu.Joueurs)
            {
                Brush b = Texture.convertirCouleur(joueur.couleur);
                foreach (InterfaceJeu.Ville ville in joueur.civilisation.villes)
                {
                    if (lc.Contains(ville.caseSousLaVille.coordo))
                    {
                        int x = ville.caseSousLaVille.coordo.abscisse;
                        int y = ville.caseSousLaVille.coordo.ordonnee;
                        var rectangle = new Rectangle();
                        rectangle.Height = 50;
                        rectangle.Width = 50;
                        rectangle.Fill = tex.getImage("Ville");
                        rectangle.Stroke = b;
                        rectangle.StrokeThickness = 2;

                        Grid.SetColumn(rectangle, x);
                        Grid.SetRow(rectangle, y);
                        gridVille.Children.Add(rectangle);
                        if (joueur == joueurcourant)
                            rectangle.MouseLeftButtonDown += new MouseButtonEventHandler(ville_MouseLeftDown);
                        else
                            rectangle.MouseLeftButtonDown += new MouseButtonEventHandler(rectangle_MouseLeftDown);
                        rectangle.MouseRightButtonDown += new MouseButtonEventHandler(rectangle_MouseRightDown);
                    }
                }
            }
        }

        /// <summary>
        /// Methode appele lors du clic gauche sur une case vide
        /// elle affiche les info de cette case
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void rectangle_MouseLeftDown(object sender, MouseButtonEventArgs e)
        {
            var coord = coordonneeClic((Rectangle)sender);
            initInfoCase(coord);
            initRectangleSelection(coord);
            initUnitePanel(coord);
            e.Handled = true;
        }

        /// <summary>
        /// Méthode appelée lors du clic droit sur une case de la Carte
        /// elle permat de déplacer l'unité courant sur cette case ou de combattre s'il s'agit d'un étudiant
        /// et que la case est occupée par des unités ou une ville ennemies
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void rectangle_MouseRightDown(object sender, MouseButtonEventArgs e)
        {
              if (uniteCourante != null)
           {
               InterfaceJeu.Coordonnees ancienne = uniteCourante.position;
               InterfaceJeu.Coordonnees nouvelle = coordonneeClic((Rectangle)sender);
               if (uniteCourante is Etudiant && test.contientUniteEnnemie(monJeu,joueurcourant,nouvelle))
               {
                   Etudiant etudiant = (Etudiant)uniteCourante;
                   Erreurs err =  etudiant.combattre(monJeu.Carte.obtenirCase(nouvelle));
                   if (err.pasErreur)
                       status.Content = "Le Combat a eu lieu";
                   else
                       status.Content = err.msg;
               }
               else
               {
                   Erreurs err = uniteCourante.seDeplacer(monJeu.Carte.obtenirCase(nouvelle));
                   status.Content = err.msg;
               }
               initCarte(joueurcourant);
               initUnite(joueurcourant.caseVisible);
               initUnitePanel(ancienne);
               initInfoCivi();
           }
        }

        /// <summary>
        /// Methode appele lors du clic gauche sur une ville
        /// elle affiche les info de cette ville
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ville_MouseLeftDown(object sender, MouseButtonEventArgs e)
        {
            var c = coordonneeClic((Rectangle)sender);
            initInfoVille(c);
            initUnitePanel(c);
            initRectangleSelection(c);
            status.Content = "";
        }

        /// <summary>
        /// Methode appele lors du clic sur une unité 
        /// elle affiche les info de la ville ou de la case sous l'unité
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void unite_MouseLeftDown(object sender, MouseButtonEventArgs e)
        {
            InterfaceJeu.Coordonnees c = coordonneeClic((Rectangle)sender);
            if (test.obtenirVille(monJeu, c) != null)
                ville_MouseLeftDown(sender, e);
            else
                rectangle_MouseLeftDown(sender, e);
        }

        /// <summary>
        /// Donne les coordonnées d'un rectangle d'une grille
        /// </summary>
        /// <param name="o">Le rectangle dont on veut les coordonées</param>
        /// <returns>Les coordonnées du rectangle passé en paramètre</returns>
        private InterfaceJeu.Coordonnees coordonneeClic(Rectangle rectangle)
        {
            int colonne = Grid.GetColumn(rectangle);
            int ligne = Grid.GetRow(rectangle);
            return new ImplementationJeu.Coordonnees(colonne, ligne);
        }

        /// <summary>
        /// Initialise des rectangles symbolisant les cases propices à la création d'une ville par un enseignant
        /// </summary>
        private void initPlaceVille()
        {
            //la présence du try cacth est du à la non sauvegarde lors de la serialisation de la carte brute creer par le wrapper
            try
            {
                PlacePourVilles ppv = new PlacePourVilles(monJeu.sonTour, uniteCourante.position.getIndex(), uniteCourante.nbMouvement - 1, monJeu.Carte.fabriqueCase.carteBrute, monJeu.Carte.TailleCote);
                ppv.run();
                vector_int suggest = ppv.get_result();
                List<InterfaceJeu.Coordonnees> l = new List<InterfaceJeu.Coordonnees>();
                if (suggest[0] != 0)
                {
                    l.Add(new ImplementationJeu.Coordonnees(suggest[0]));
                }
                if (suggest[1] != 0)
                {
                    l.Add(new ImplementationJeu.Coordonnees(suggest[1]));
                }
                if (suggest[2] != 0)
                {
                    l.Add(new ImplementationJeu.Coordonnees(suggest[2]));
                }
                initVille(joueurcourant.caseVisible);
                foreach (InterfaceJeu.Coordonnees coord in l)
                {
                    var rectangle = new Rectangle();
                    rectangle.Height = 50;
                    rectangle.Width = 50;
                    rectangle.Fill = Brushes.Red;
                    rectangle.Opacity = 0.3;
                    rectangle.MouseLeftButtonDown += new MouseButtonEventHandler(rectangle_MouseLeftDown);
                    rectangle.MouseRightButtonDown += new MouseButtonEventHandler(rectangle_MouseRightDown);
                    Grid.SetColumn(rectangle, coord.abscisse);
                    Grid.SetRow(rectangle, coord.ordonnee);
                    gridVille.Children.Add(rectangle);
                }
            }
            catch (Exception e)
            {
                status.Content = "";
            }
        }

        /// <summary>
        /// Initialise le panneau contenant les informations des unités présentes sur une case
        /// </summary>
        /// <param name="c">la coordonnee de la case dont on doit afficher les unités</param>
        private void initUnitePanel(InterfaceJeu.Coordonnees c)
        {  
            unitePanel.Items.Clear();
            unitePanelAutreJoueur.Items.Clear();
            List<InterfaceJeu.Unite> l = test.obtenirUnite(joueurcourant, c);
            unitePanel.Visibility = Visibility.Hidden;
            GroupUnite.Visibility = Visibility.Hidden;
            unitePanelAutreJoueur.Visibility = Visibility.Hidden;
            if (l.Count == 0)
            {
                l = test.obtenirUniteAutreJoueur(monJeu,joueurcourant, c);
                if (l.Count != 0)
                {
                    foreach (InterfaceJeu.Unite unite in l)
                        unitePanelAutreJoueur.Items.Add(unite);
                    unitePanelAutreJoueur.Visibility = Visibility.Visible;
                    GroupUnite.Visibility = Visibility.Visible;
                }
            }
            else
            {
                foreach (InterfaceJeu.Unite unite in l)
                   unitePanel.Items.Add(unite);
                unitePanel.Visibility = Visibility.Visible;
                GroupUnite.Visibility = Visibility.Visible;
                unitePanel.SelectedItem = unitePanel.Items.GetItemAt(0);
            }
        }

        /// <summary>
        /// Initialise le panneau contenant les informations d'une ville
        /// </summary>
        /// <param name="c">la coordonnee de la ville dont on doit afficher les informations</param>
        private void initInfoVille(InterfaceJeu.Coordonnees c)
        {
            InterfaceJeu.Ville ville = test.obtenirVille(monJeu, c);
            villeCourante = ville;
            labelVille.Content = String.Format("Population : {0}      Nourriture stockée : {1}         Minerai stocké : {2} \nUnite en production : {3}          Attente : {4} tour",
                ville.population, ville.ressources["nourriture"], ville.ressources["minerai"], test.obtenirUniteEnAttente(ville), ville.dureeAttenteProduction);
            GroupInfo.Header = "Informations sur la ville";
            labelCase.Visibility = Visibility.Hidden;
            labelVille.Visibility = Visibility.Visible;
            GroupVille.Visibility = Visibility.Visible;
        }

        /// <summary>
        /// Initialise le rectangle indiquant la selection d'une case à une coordonnée donnée
        /// </summary>
        /// <param name="c">la coordonnee ou initialise le rectangle de sélection</param>
        private void initRectangleSelection(InterfaceJeu.Coordonnees c)
        {
            Grid.SetColumn(rectangleSelection, c.abscisse);
            Grid.SetRow(rectangleSelection, c.ordonnee);
            rectangleSelection.Visibility = Visibility.Visible;
        }

        /// <summary>
        /// Initialise le label contenant les information de la case
        /// </summary>
        /// <param name="coord">les coordonnées de la case à partir de laquelle on doit initialiser les informations</param>
        private void initInfoCase(InterfaceJeu.Coordonnees coord)
        {
            InterfaceJeu.Case c = monJeu.Carte.obtenirCase(coord);
            labelCase.Content = String.Format(" Minerai {0} Nouriture {1}", c.minerai, c.nourriture);
            labelCase.Visibility = Visibility.Visible;
            GroupInfo.Header = "Informations sur la case";
            labelVille.Visibility = Visibility.Hidden;
            GroupVille.Visibility = Visibility.Hidden;
            unitePanel.Visibility = Visibility.Hidden;
        }

        /// <summary>
        /// Initialise le label contennt les informations de la civilisation du joueur courant
        /// </summary>
        private void initInfoCivi()
        {
            InfoCivi.Content = String.Format("La civilisation de {2} possèdent {0} villes et {1} unités.", joueurcourant.civilisation.villes.Count, joueurcourant.civilisation.unites.Count, joueurcourant.nom);
        }

        /// <summary>
        /// Initialise le scrollViewer de la carte à la position de la première ville du joueur courant
        /// </summary>
        private void initScroll()
        {
            InterfaceJeu.Coordonnees c = joueurcourant.civilisation.villes[0].caseSousLaVille.coordo;
            scrollViewer1.UpdateLayout();
            scrollViewer1.ScrollToVerticalOffset((c.ordonnee / (monJeu.Carte.TailleCote - 1)) * scrollViewer1.ScrollableHeight);
            scrollViewer1.ScrollToHorizontalOffset((c.abscisse / (monJeu.Carte.TailleCote - 1)) * scrollViewer1.ScrollableWidth);
        }

        /// <summary>
        /// Initialise le label indiquant qui doit jouer
        /// </summary>
        private void initLabelTour()
        {
            labelTour.Content = String.Format("C'est à {0} de jouer !", joueurcourant.nom);
            labelTour.BorderBrush = Texture.convertirCouleur(joueurcourant.couleur);
            labelTour.BorderThickness = new Thickness(5);
        }


        //////////////////////////////////////////////////////////////////////////////////////////////////
        // Gestionnaire des boutons de gestion du tour de Jeu
        //////////////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Méthode appelée lors du click sur la croix 
        /// elle ferme l'application
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Cross_Click(object sender, EventArgs e)
        {
            Application.Current.Shutdown(0);
        }

        /// <summary>
        /// Méthode appelée lors du click sur le Bouton de sauvegarde 
        /// elle ouvre une fenetre de hoix et lance la sérialisation
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonSauvegarder_Click(object sender, RoutedEventArgs e)
        {
            //Chargement de toutes les cartes
            int taille = ImplementationJeu.Jeu.Instance.Carte.TailleCote;
            for (int index = 0; index < taille * taille; index++)
            {
                ImplementationJeu.Jeu.Instance.Carte.obtenirCase(new ImplementationJeu.Coordonnees(index));
            }

            Microsoft.Win32.SaveFileDialog boiteSauvegarde = new Microsoft.Win32.SaveFileDialog();
            boiteSauvegarde.Filter = "Fichier insa(*.insa)|*.insa";
            if (boiteSauvegarde.ShowDialog() == true)
            {
                ImplementationJeu.Jeu.Instance.sauvegarderPartie(boiteSauvegarde.FileName);
            }
        }

        /// <summary>
        /// Methode appellé lors du click sur le bouton fin de tour
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FinTour_Click(object sender, RoutedEventArgs e)
        {
            status.Content = "";
            //test fin de partie
            if (monJeu.estTermine())
            {
                List<string> joueursClasses = new List<string>();
                joueursClasses.Add(ImplementationJeu.Jeu.Instance.gagnant.nom);
                for (int i = ImplementationJeu.Jeu.Instance.classement.Count - 1; i >= 0; i--)
                {
                    InterfaceJeu.Joueur jj = ImplementationJeu.Jeu.Instance.classement[i];
                    joueursClasses.Add(jj.nom);
                }
                App.getApp().afficheFinDePartie(joueursClasses);//Passer le classement en param
                this.Visibility = Visibility.Hidden;
            }
            else
            {
                monJeu.jouerLeJeu();
                joueurcourant = monJeu.Joueurs[monJeu.sonTour];
                initLabelTour();
                initCarte(joueurcourant);
                initInfoCivi();
                initScroll();
                labelCase.Visibility = Visibility.Hidden;
                labelVille.Visibility = Visibility.Hidden;
                GroupUnite.Visibility = Visibility.Hidden;
                
            }
        }

        /// <summary>
        /// Methode appellee lors du clic sur le bouton Abandonner
        /// cette methode appele automatiquement la methode Fin de tour
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BoutonAbandonner_Click(object sender, RoutedEventArgs e)
        {
            joueurcourant.abandonnerPartie();
            status.Content = String.Format("{0} a abandonné !", joueurcourant.nom);
            FinTour_Click(sender, e);
        }

        //////////////////////////////////////////////////////////////////////////////////////////////////
        // Gestionnaire des boutons de Creation des Unites
        //////////////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Methode appellee lors du clic sur le bouton creer enseignant
        /// elle demande à la ville courante de produire un enseignant
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BoutonCreerEnseignant_Click(object sender, RoutedEventArgs e)
        {
            Erreurs err = villeCourante.commanderUnite((int)ImplementationJeu.Ville.UniteType.ENSEIGNANT);
            status.Content = err.msg;
            initInfoVille(villeCourante.caseSousLaVille.coordo);
        }

        /// <summary>
        /// Methode appellee lors du clic sur le bouton creer Directeur
        /// elle demande à la ville courante de produire un Directeur
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BoutonCreerDirecteur_Click(object sender, RoutedEventArgs e)
        {
            Erreurs err = villeCourante.commanderUnite((int)ImplementationJeu.Ville.UniteType.DIRECTEUR);
            status.Content = err.msg;
            initInfoVille(villeCourante.caseSousLaVille.coordo);
        }

        /// <summary>
        /// Methode appellee lors du clic sur le bouton creer etudiant
        /// elle demande à la ville courante de produire un etudiant
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BoutonCreerEtudiant_Click(object sender, RoutedEventArgs e)
        {
            Erreurs err = villeCourante.commanderUnite((int)ImplementationJeu.Ville.UniteType.ETUDIANT);
            status.Content = err.msg;
            initInfoVille(villeCourante.caseSousLaVille.coordo);
        }


        //////////////////////////////////////////////////////////////////////////////////////////////////
        // Gestionnaire Du bouton Creer Ville
        //////////////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Methode appellee lors du clic sur le bouton creer Ville
        /// elle demande à l'unite courante si celle ci est un enseignant de creer une ville à sa position
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BoutonCreerVille_Click(object sender, RoutedEventArgs e)
        {
            if (uniteCourante is Enseignant)
            {
                Enseignant ens = (Enseignant)uniteCourante;
                InterfaceJeu.Coordonnees c = ens.position;
                Erreurs err = ens.creerVille();
                status.Content = err.msg;
                if (err.pasErreur)
                {
                    initCarte(joueurcourant);
                    initUnitePanel(c);
                    initInfoVille(c);
                    initInfoCivi();
                }
            }
        }

        //////////////////////////////////////////////////////////////////////////////////////////////////
        // Gestionnaire du changemnt de Selection du pannel d'unité
        //////////////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Méthode appelée lors du changment de selection dans le pannel d'unité elle actualise l'unité courante
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void unitePanel_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var list = sender as ListBox;
            labelVille.BorderThickness = new Thickness(0);
            GroupAction.Visibility = Visibility.Hidden;
            InterfaceJeu.Unite unite = (Unite)list.SelectedItem;
            uniteCourante = unite;
            initVille(joueurcourant.caseVisible);
            if (unite is Enseignant && unite.nbMouvement > 0)
            {
                GroupAction.Visibility = Visibility.Visible;
                initPlaceVille();
            }
        }

        //////////////////////////////////////////////////////////////////////////////////////////////////
        // Gestionnaire Des entrees clavier
        //////////////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Methode appelle lors de l'appui sur une touche du clavier
        /// La touche entrer execute la meme action que fin de tour
        /// La touche espace permet de faire défiler les unites
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Window_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                FinTour_Click(sender, e);
            }
            if (e.Key == Key.Space)
            {
                if(unitePanel.IsVisible)
                unitePanel.SelectedIndex = (unitePanel.SelectedIndex + 1) % unitePanel.Items.Count;
            }
        }
    }
}
